/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "core/文件块.h"
#include "S_物体.h"
#include "引擎数据类型.h"

#include <面/Mesh.h>


typedef vec3(*fp_坐标转换)(const vec3& vert);




EngineAPI_EXPORT S_物体*	f_ob_创建(E_物体类型 type, S_物体* froObj, S_设备环境 ctx);
EngineAPI_EXPORT S_物体*	f_ob_创建(S_设备环境& ctx, E_物体类型 type);

EngineAPI_EXPORT S_物体*	f_ob_创建(E_物体类型 type);
EngineAPI_EXPORT S_物体*	f_ob_创建实例(S_物体* 父物体, uint32 loc);

EngineAPI_EXPORT void		f_ob_setName(S_物体* ob, const std::u16string& name);

EngineAPI_EXPORT S_物体*	f_ob_添加实例(S_物体* 父物体, uint32 实例ID = -1);

EngineAPI_EXPORT S_物体*    f_ob_创建灯光(S_设备环境& ctx, E_物体类型 type);
EngineAPI_EXPORT void		f_ob_销毁(S_物体* 物体);
EngineAPI_EXPORT void		f_ob_改变物体类型(S_物体* ob, E_物体类型 type);

EngineAPI_EXPORT S_物体*	f_创建BOX物体(const vec3& size, S_设备环境 ctx, bool 三角化 = true, E_绘图API engineType = E_绘图API::E_Vulkan);
EngineAPI_EXPORT S_物体*	f_创建圆柱物体(const vec3& 高_半径, uint32 细分, S_设备环境 ctx, bool 三角化 = true, E_绘图API engineType = E_绘图API::E_Vulkan);
EngineAPI_EXPORT S_物体*	f_创建球体物体(const float32 半径, uvec2 细分, S_设备环境 ctx, bool 三角化=true, E_绘图API engineType = E_绘图API::E_Vulkan);

EngineAPI_EXPORT void		f_ob_构建骨骼虚拟体实例ID(S_物体* ob, uint32& d);
EngineAPI_EXPORT void		f_ob_构建骨骼(S_物体* ob, S_物体* 骨骼物体, S_物体* 骨节物体, S_物体* 骨骼辅助虚拟物体);
EngineAPI_EXPORT void		f_ob_绑定网格骨骼(S_物体* ob, S_物体* bonse, uint32 mesh_loc);


EngineAPI_EXPORT S_摄像机*	f_ob_创建摄像机(S_设备环境 ctx, E_绘图API engineType = E_绘图API::E_Vulkan);
EngineAPI_EXPORT void		f_ob_销毁摄像机(S_摄像机* camera);



EngineAPI_EXPORT void		f_ob_link物体数据(S_物体* ob, S_物体* froObj);
//EngineAPI_EXPORT S_物体*	f_ob_copy到新物体(S_设备环境& ctx, S_物体* froObj);
EngineAPI_EXPORT S_物体*	f_ob_copy(S_设备环境& ctx, S_物体* ob, bool 链接 = true);
EngineAPI_EXPORT void		f_ob_set数据槽数量(S_物体* ob, uint32 num);
EngineAPI_EXPORT void		f_ob_set安装网格(S_物体* ob, std::vector<S_网格包>& pack);
EngineAPI_EXPORT void		f_ob_set数据(S_物体* Obj, void* data, uint8 loc = 0);
EngineAPI_EXPORT S_网格包&	f_ob_set数据(S_物体* ob, S_Mesh* me, uint8 loc = 0);
EngineAPI_EXPORT S_网格包&	f_ob_get数据(S_物体* ob, uint8 loc = 0);

const S_网格包&					f_ob_get数据(const S_物体* ob, uint8 loc = 0);
std::vector<S_网格包>&			f_ob_get网格包(S_物体* ob);
const std::vector<S_网格包>&	f_ob_get网格包(const S_物体* ob);


EngineAPI_EXPORT void		f_ob_set实例数量(S_物体* Ob, uint32 num, bool 创建物体 = true);
EngineAPI_EXPORT void		f_ob_fill实例ID(S_物体* Ob);
EngineAPI_EXPORT void		f_ob_fill实例(S_物体* Ob, uint32 num);
EngineAPI_EXPORT void		f_ob_set为实例(S_物体* Obj);
EngineAPI_EXPORT void		f_ob_set物体数据可视(S_物体* Obj, uint8 loc, bool 是否可视);
EngineAPI_EXPORT void		f_ob_set线宽(S_物体* Obj, float32 h, uint8 loc = 0);
EngineAPI_EXPORT void		f_ob_set细分(S_物体* Obj, uint32 次数, uint8 loc = 0);
EngineAPI_EXPORT void		f_ob_set网格可视(S_物体* ob, bool show, uint8 loc = 0);
EngineAPI_EXPORT void		f_ob_set附属类型(S_物体* ob, E_物体类型 类型);
EngineAPI_EXPORT E_物体类型	f_ob_get附属类型(S_物体* ob);


EngineAPI_EXPORT void		f_ob_set材质(S_物体* Obj, S_材质管线* mat, uint8 loc = 0, int32 槽 = 0);
EngineAPI_EXPORT void		f_ob_set颜色2(S_物体* Obj, S_RGBA8UI color, uint32 offset, uint8 槽 = 0);
EngineAPI_EXPORT void		f_ob_set颜色(S_物体* Obj, const S_RGBA8UI& color);
EngineAPI_EXPORT void		f_ob_set粒子数量(S_物体* Obj, uint32 num);
EngineAPI_EXPORT void		f_ob_set粒子位置(S_物体* Obj, const vec3* l, uint32 num);
EngineAPI_EXPORT void		f_ob_set粒子速度(S_物体* Obj, const vec3* v, uint32 num);
EngineAPI_EXPORT void		f_ob_set粒子旋转(S_物体* Obj, const vec3* r, uint32 num);
EngineAPI_EXPORT void		f_ob_set粒子大小(S_物体* Obj, const vec3* s, uint32 num);
EngineAPI_EXPORT void		f_ob_set粒子渲染物体(S_物体* Obj, E_粒子绘制类型 绘制类型);
EngineAPI_EXPORT S_粒子系统配置*		f_ob_fromParticle(S_物体* ob, uint32 loc = 0);



EngineAPI_EXPORT void		f_ob_copy骨骼(S_物体* d_ob, const S_物体* s_ob);

EngineAPI_EXPORT void		f_ob_copyData(S_物体* ob, S_物体* 源物体, bool 链接 = true);
EngineAPI_EXPORT void		f_ob_copyIK(S_骨骼IK* s_ik, S_骨骼IK* ik);


EngineAPI_EXPORT S_Mesh*		f_ob_fromTranformMesh(S_物体* froObj, uint32 loc = 0);

//Inline S_Mesh* f_ob_Mesh(S_物体* ob, uint32 id = 0) {
//	return (S_Mesh*)(ob->m_Data[id]);
//}
EngineAPI_EXPORT S_Mesh*		f_ob_getMesh(const S_物体* froObj, uint32 loc = 0);
EngineAPI_EXPORT S_材质管线*	f_ob_get材质(const S_物体* ob, uint32 loc, int32 多维子元素 = 0);
EngineAPI_EXPORT S_Material&	f_ob_get材质属性(uint32& 材质ID, const S_物体* ob, uint32 loc, int32 多维子元素 = 0);
EngineAPI_EXPORT S_灯光场景数据* f_ob_getLigth(const S_物体* ob, uint32 loc = 0);



EngineAPI_EXPORT S_LightParallel* f_ob_fromParallelLigth(S_物体* froObj);
EngineAPI_EXPORT S_LightSpot* f_ob_fromLigthSpot(S_物体* froObj);
EngineAPI_EXPORT S_LightPoint* f_ob_fromLigthPoint(S_物体* froObj);
EngineAPI_EXPORT S_LightArea* f_ob_fromAreaLigth(S_物体* froObj);
//S_灯光场景数据* f_ob_fromLigthSceneData(S_物体* froObj);

EngineAPI_EXPORT uint32		f_ob_get数量层数量(S_物体* ob);
EngineAPI_EXPORT uint32		f_ob_get实例数量(S_物体* Obj);
EngineAPI_EXPORT uint32		f_ob_get顶点数量(S_物体* Obj);
EngineAPI_EXPORT float32	f_ob_get最大半径(S_物体* Obj);
EngineAPI_EXPORT S_Sphere	f_ob_get范围(S_物体* Obj);
EngineAPI_EXPORT S_物体*	f_ob_get子对象(S_物体* Obj, uint32 offset);
EngineAPI_EXPORT S_物体*	f_ob_get实例ID对象(S_物体* Obj, uint32 ID);
EngineAPI_EXPORT S_物体*    f_ob_get父变换对象(S_物体* Obj);
EngineAPI_EXPORT vec3		f_ob_get全局坐标(S_物体* Obj, uint32 ID);


EngineAPI_EXPORT S_物体*	f_ob_from实例对象取父对象(S_物体* Obj);
EngineAPI_EXPORT E_物体类型	f_ob_get可视对象类型(S_物体* Obj);
EngineAPI_EXPORT uint64		f_ob_get子物体数量(S_物体* Ob, bool 包括子集 = false);
EngineAPI_EXPORT S_物体*	f_ob_以类型查找子物体(S_物体* ob, E_物体类型 type);


EngineAPI_EXPORT uint32		f_ob_add子物体(S_物体* 父, S_物体* 子, uint32 loc = 0xffffffff);
EngineAPI_EXPORT void		f_ob_add实例物体(S_物体* 父, S_物体* 子物体, uint32 loc = 0xffffffff);
EngineAPI_EXPORT void		f_ob_ins实例物体(S_物体* 父, uint32 实例ID, uint32 loc = 0xffffffff);
EngineAPI_EXPORT void		f_ob_set实例物体(S_物体* 父, S_物体* 子, uint32 loc = 0xffffffff);
EngineAPI_EXPORT void		f_ob_clear子物体(S_物体* 父, uint64 s = 0, uint64 e = -1);
EngineAPI_EXPORT void		f_ob_从父物体中移除(S_物体* ob);
EngineAPI_EXPORT void		f_ob_销毁子物体(S_物体* 父, uint64 s = 0, uint64 e = -1);

EngineAPI_EXPORT void f_ob_清除子物体(S_物体* 父);

EngineAPI_EXPORT vec3 f_ob_getLoc(S_物体* ob, uint32 id = 0);
EngineAPI_EXPORT vec3 f_ob_getRot(S_物体* ob, uint32 id = 0);
EngineAPI_EXPORT vec3 f_ob_getScale(S_物体* ob, uint32 id = 0);

EngineAPI_EXPORT void f_ob_setLoc(S_物体* ob, const vec3& loc, uint32 id = 0);
EngineAPI_EXPORT void f_ob_setRot(S_物体* ob, const vec3& rot, uint32 id = 0);
EngineAPI_EXPORT void f_ob_setScale(S_物体* ob, const vec3& scal);
EngineAPI_EXPORT void f_ob_setScale(S_物体* ob, const vec3& scal, uint32 id);
EngineAPI_EXPORT void f_ob_setTranform(S_物体* ob, const S_Tranform& tran);

Inline S_MeshTranformProp& f_ob_get网格变换属性(S_物体* ob, uint32 槽, uint32 offset) {
	return f_mesh_get网格元素绘制属性(f_ob_getMesh(ob, 槽), offset);
}

Inline void f_ob_set显示(S_OBArray* obs, bool 显示) {
	for (uint32 i = 0; i < obs->count; ++i) {
		obs->ptr_userData[i]->m_显示 = 显示;
	}
}


EngineAPI_EXPORT void f_ob_Load物体(S_物体* ob, FILE* f);
EngineAPI_EXPORT void f_ob_Save物体(S_物体* ob, FILE* f);

const uint8* f_ob_Load物体(S_设备环境& ctx, S_物体** ob, const uint8* 块);
void f_ob_Save物体(const S_物体* ob, S_UI8Array* 块);

//const uint8* f_ob_Load多边形(S_物体** ob, const uint8* 块);
//void f_ob_Save多边形(const S_物体* ob, S_UI8Array* 块);



EngineAPI_EXPORT const uint8* f_ob_Load多物体(S_OBArray* obs, const uint8* 块, S_设备环境& ctx);
EngineAPI_EXPORT void f_ob_Save多物体(const S_OBArray* obs, S_UI8Array* 块);

EngineAPI_EXPORT const uint8* f_ob_Load多物体(S_OBArray* obs, const uint8* 块, S_设备环境& ctx, bool 数据, fp_创建物体几何数据 模型创建回调);
EngineAPI_EXPORT void f_ob_Save多物体(const S_OBArray* obs, S_UI8Array* 块, bool 数据, bool 压缩);

EngineAPI_EXPORT const uint8* f_ob_Load模型(S_物体** obs, const uint8* 块, S_设备环境& ctx, bool 数据, fp_创建物体几何数据 模型创建回调);
EngineAPI_EXPORT void f_ob_Save模型(const S_物体* obs, S_UI8Array* 块, bool 数据);
EngineAPI_EXPORT void f_ob_Save模型(const S_物体* obs, S_UI8Array* 块, bool 数据, E_物体类型 物体类型);



//		void f_ob_递归保存物体(const S_物体* ob, S_UI8Array* 块, bool 数据 = false);
EngineAPI_EXPORT const uint8* f_ob_递归加载物体(S_OBArray* obs, const uint8* 块, S_设备环境& ctx);
EngineAPI_EXPORT 		void f_ob_递归保存物体(const S_OBArray* obs, S_UI8Array* 块);

EngineAPI_EXPORT void f_ob_复制物体属性(S_OBArray* d_ob, const S_OBArray* s_ob);


EngineAPI_EXPORT void f_ob_Load多物体(S_OBArray* objs, FILE* f, S_设备环境& ctx, bool 数据 = false);
//void f_ob_Save多物体(const S_OBArray* objs, FILE* f, bool 数据 = false);


EngineAPI_EXPORT void f_load物体(FILE* f, S_物体* obj);
EngineAPI_EXPORT void f_save物体(FILE* f, S_物体* obj);

EngineAPI_EXPORT std::vector<S_物体*> f_load多物体(FILE* f, S_设备环境 ctx);
EngineAPI_EXPORT void f_save多物体(FILE* f, const std::vector<S_物体*>& objs);

EngineAPI_EXPORT std::vector<S_物体*> f_ob_loadFBX(const std::string& path, float32 预缩放, S_设备环境& ctx);
EngineAPI_EXPORT std::vector<S_物体*> f_ob_loadOBJ(const std::string& path, S_设备环境 ctx, std::vector<S_纹理添加列队>& 纹理加载列队);

EngineAPI_EXPORT void f_ob_load(S_物体* ob, const S_Props& path, const S_Props& 类型后缀, const S_Props& 平滑法线, S_设备环境& ctx);
EngineAPI_EXPORT void f_ob_Save(S_物体* ob, const S_Props& path, const S_Props& 类型后缀, const S_Props& 平滑法线);
EngineAPI_EXPORT std::u16string f_ob_Save(S_物体* ob, const std::u16string& path, const std::u16string& 后缀名称, bool 平滑法线, fp_坐标转换 fn=nullptr);








/****************************** 物体变换操作 ********************************/
EngineAPI_EXPORT vec3 f_obj_get方向(S_物体* obj, E_轴向 轴向);
EngineAPI_EXPORT vec3 f_ob_get中心(const std::vector<S_物体*>& obs, bool 包括子对象 = false);
EngineAPI_EXPORT void f_ob_增量移动(S_物体* obj, vec3 距离);
EngineAPI_EXPORT void f_ob_set缩放(S_物体* obj, const vec3& 缩放);




EngineAPI_EXPORT float32 f_camera_get相机到视点距离(const S_摄像机* camera);
EngineAPI_EXPORT vec3	f_camera_get眼睛位置(const S_摄像机& camera);
EngineAPI_EXPORT vec3	f_camera_get视点位置(const S_摄像机& camera);
EngineAPI_EXPORT vec3	f_camera_get原点位置(const S_摄像机& camera);

EngineAPI_EXPORT void	f_camera_set摄像机视点位置(S_摄像机& camera, vec3 pos);
EngineAPI_EXPORT void	f_camera_set摄像机视点移动到偏移点(S_摄像机& camera);
EngineAPI_EXPORT void	f_camera_set偏移视点(S_摄像机& camera, const vec3& pos);
EngineAPI_EXPORT void	f_camera_set旋转距离(S_摄像机& camera, const vec3& rot, float32 dis);
EngineAPI_EXPORT void	f_camera_set旋转限制(S_摄像机& camera, const vec3 最小, const vec3 最大, bool 限制X轴, bool 限制Y轴, bool 限制Z轴);
EngineAPI_EXPORT vec3	f_camera_get相机视线平移方向(const S_摄像机& camera, vec3& H, vec3& V);
EngineAPI_EXPORT vec3	f_camera_get视线向量(const S_摄像机& camera);
EngineAPI_EXPORT vec3	f_camera_计算摄像机以角度缩放大小(S_摄像机* camera);

void f_camera_set转盘旋转(S_摄像机& camera, const vec3& rot);
void f_camera_scal转盘距离(S_摄像机& camera, float32 dis);
void f_camera_set转盘视点平移(S_摄像机& camera, vec2 move);
void f_camera_set转盘视点增量平移(S_摄像机& camera, vec2 move);

void f_camera_开始相机变换(S_摄像机& camera, vec2 开始空间点坐标);
void f_camera_结束相机变换();

mat4		f_camera_get视图投影(const S_摄像机* camera);
S_板载缓存* f_camera_get变换矩阵(const S_摄像机* camera);
Mat44f		f_camera_计算变换矩阵(const S_摄像机& camera);



void f_ob_更新变换约束(S_物体* ob, const Mat44f* 父级变换);




/***************************** 扩展预设物体 ******************************/

void	f_ob_创建天空网格(S_设备环境& ctx, S_物体* ob, uint32 槽);
S_物体*	f_ob_创建区域光(S_设备环境& ctx);
void	f_ob_创建U型桶(S_设备环境& ctx, S_物体* ob, uint32 槽, float32 圆角比例);






/***************************** 扩展物体参数设置 *****************************/

EngineAPI_EXPORT void f_ob_set域(S_物体* Obj, S_DomProp& 域绘制参数, uint8 loc = 0);
EngineAPI_EXPORT void f_fromMesh创建体素(S_Mesh* srcMesh, const Mat44f& mat, float 间距, std::vector<vec3>& vert);

S_物体* f_ob_创建基准网格线(S_设备环境& ctx);




/***************************** 物体光追数据构建 *****************************/
EngineAPI_EXPORT void f_ob_构建顶层光追加速结构(S_OBArray* obs, S_渲染层* 层);
EngineAPI_EXPORT void f_ob_构建顶层光追加速结构(std::vector<S_Object*>& obs, S_渲染层* 层);
EngineAPI_EXPORT void f_ob_构建顶层光追加速结构(std::map<std::wstring, S_Object*>& obs, S_渲染层* 层);
EngineAPI_EXPORT void f_ob_构建顶层光追加速结构(S_渲染层* 层, S_渲染对象** 渲染对象, uint32 num);


EngineAPI_EXPORT void f_ob_光追加速结构描述集(S_渲染世界* 世界);
EngineAPI_EXPORT void f_ob_光追加速结构描述集(S_物体** ob, uint32 num, void** descriptor);
EngineAPI_EXPORT void f_ob_光追加速结构描述集(S_GPU内存块& 内存块, void** descriptor);
EngineAPI_EXPORT void f_ob_销毁光追加速结构描述集(void* descriptor);
EngineAPI_EXPORT uint32 f_ob_get光追加速结构描述集数量(void* descriptor);





/***************************** 灯光 *****************************/

void f_light_构建阴影图(S_灯光场景数据* data, uvec2 size, uint32 num);
void f_light_set阴影贴图大小(S_灯光场景数据* data, uvec2 size, int32 层 = 0);

Mat44f f_light_计算区域光视口(S_灯光场景数据* data, float32 散度, const Mat44f& mat);




/***************************** 渲染 *****************************/

void f_ob_render_begin(S_设备环境& ctx, S_摄像机& 摄像机, C_场景渲染环境& 管线槽);

void f_ob_render_view(S_设备环境& ctx, const S_Viewport& 视口, const S_Rect2D& 裁剪, vec2* offset);

void f_ob_render(S_物体* ob, E_管线槽 管线槽, uint32 fb = 0xffffffff);
void f_ob_render(S_物体* ob, uint32 材质ID);

void f_ob_render_s(S_物体* ob, E_管线槽 管线槽, uint32 loc);


